package game.breeze.gameserver.message;

import game.breeze.Constants.Constants;
import game.breeze.data.Player;
import game.breeze.gameserver.World;
import game.breeze.gameserver.controller.PlayerController;
import game.breeze.gameserver.job.ClientMessageJob;
import game.breeze.gameserver.listener.SocketConnectionCallback;
import game.breeze.message.AppMessage;
import game.breeze.message.Message;
import game.breeze.message.codec.IMessageCodecFactory;
import game.breeze.resource.manager.GameResourceManager;
import game.breeze.socket.connection.MinaConnection;
import game.breeze.socket.connection.NetConnection;
import game.breeze.socket.connection.listener.NetConnectionListener;
import game.breeze.socket.util.ByteBufferWrapper;
import game.breeze.socket.util.JobQueueOB;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.mina.core.session.IoSession;

public class MessageInterceptor implements MethodInterceptor, SocketConnectionCallback, NetConnectionListener {
	private IMessageCodecFactory factory;
	private GameResourceManager resource;
	private World world;

	public MessageInterceptor(IMessageCodecFactory fac, GameResourceManager resManager, World world) {
		this.factory = fac;
		this.resource = resManager;
		this.world = world;
		this.world.init(resource);
	}

	@Override
	public Object invoke(MethodInvocation invocation) throws Throwable {
		methodBefore(invocation);
		Object execute = invocation.proceed();
		methodAfter(invocation);
		return execute;
	}

	private void methodBefore(MethodInvocation invocation) {
		String method = invocation.getMethod().getName();
		Object[] arguments = invocation.getArguments();
		IoSession session = (IoSession) arguments[0];
	}

	private void methodAfter(MethodInvocation invocation) {
		String method = invocation.getMethod().getName();
		Object[] arguments = invocation.getArguments();
		IoSession session = (IoSession) arguments[0];
		if (method.equals("sessionOpened")) {
			connectionOpend(session);
		} else if (method.equals("sessionClosed")) {
			connectionClosed(session);
		}
	}

	@Override
	public void connectionClosed(IoSession session) {
		MinaConnection connection = (MinaConnection) session.getAttribute(Constants.CONNECTION_KEY);
		if (connection.getAttachment() != null && connection.getAttachment() instanceof IMessageable) {
			((IMessageable) connection.getAttachment()).setConnection(null);
		}
		connection.setMessageEncoder(null);
		connection.setMessageDecoder(null);
		connection.setMessageQueue(null);
		connection.setAttachment(null);
		session.setAttribute(Constants.CONNECTION_KEY, null);
		session.close(true);
	}

	@Override
	public void connectionOpend(IoSession session) {
		try {
			MinaConnection connection = new MinaConnection(session, new ByteBufferWrapper());
			PlayerController controller = new PlayerController(connection, new Player());
			session.getConfig().setBothIdleTime(10);
			session.setAttribute(Constants.CONNECTION_KEY, connection);
			connection.setMessageDecoder(factory.createDecoder());
			connection.setMessageEncoder(factory.createEncoder());
			connection.setAttachment(controller);
			connection.addListener(this);
			world.addController(controller);
			world.getMapController(10002).addController(controller);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public void messageArrived(NetConnection conn, Message msg) {
		msg.addTransientArg(Constants.MESSAGE_TRANSIENT_RESOURCE, resource);
		msg.addTransientArg(Constants.MESSAGE_TRANSIENT_WORLD, world);
		game.breeze.message.AppMessage appMsg = (AppMessage) msg;
		JobQueueOB.getInstance().addJob(0, new ClientMessageJob(conn, appMsg));
	}
}
